1.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I5df772ed3e39964d026b19f8d7fa34caf7f0eeb2
Code Smell Term: code smell
Code Smell Discussions: 
1)	Reviewer: The fact that this is now a one liner feels like code smell. I'm not sure, but it may indicate improper decomposition of some of these test methods.
2)	Developer: I think I see where you're coming from with this. I'm going to have another look.
Source Code URL: https://review.opendev.org/#/c/122760/8..9/nova/tests/virt/vmwareapi/test_vmops.py@1184
2.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I8913fbe82b7a9efab92d3f2eb725c2e55ffa87df
Code Smell Term: code smell
Code Smell Discussions: 
1)	Reviewer: Again, not something for this patch, but it's really inelegant that these particular methods have to be overriden like this for a NOOP mounter.
Really sort of a code smell, more than anything.
Source Code URL: https://review.opendev.org/#/c/77916/1..2/nova/virt/disk/mount/noop.py@19
3.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I2d1bbdbd4a391ad3487da905df2e812166a837de
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: I don't think that printing non-relevant tracebacks is a solution to this test problem. It can end up making it harder to debug by adding more noise to find the signal in.
Like normal code, using exception for flow control in tests is an anti-pattern.
Catching Exception also leads to fragile tests. For instance, the only other place I can find that uses this same idiom has a bug in it directly because it catches all exceptions and ignores them:
https://bugs.launchpad.net/nova/+bug/1378088
It really feels like you are really trying to shoe horn these tests into the existing code instead of making the code fit the test.
There has to be a better way of testing this.
2)	Developer: What gives you the impression that the tests use exception handling for flow control? The exception is irrelevant, nothing else.
By irrelevant, I mean that we don't care whether there is an exception or not. If there was an exception, we don't care what it was. We just don't care. Why would I change the code in order to expose something we don't care about, which has no bearing on the success or failure of the test, owing to it having happened after the event we're testing? It doesn't make sense. The refactoring you're asking for has no purpose.
I just looked at the change you added me to. I see it's been merged, but that's another example of the exception being caught being entirely irrelevant. In fact, I'm inclined to propose a revert, because you've made the test unnecessarily fragile, which was the only reason I'd had to touch it in the first place.
Let me explain: in the above change, the only thing we care about is that spawn log a scrubbed message. Literally, that's the only thing that test is interested in. We don't care, for example, if it created an instance. We don't care if it failed. We don't care why it failed. We only care that it scrubbed its log message. Your change means that some change in spawn() which causes a new exception to be thrown in a different place might cause that test to fail, despite the fact that spawn logged a scrubbed message. i.e. A false negative.
I understand your general principal, but please consider that it might not apply in all circumstance. Consider what the purpose of testing is, and consider the scope of the tests in question. The exceptions are not relevant. Making code changes based on that is just busy work and unnecessary complexity.
3)	Reviewer: Best practices exist for a reason.
Using 'except Exception' is bad practice. Yes, you can make it work with a lot of diligence. You still shouldn't do it.
The bug I fixed in the other case is a perfect example of why it's a bad practice. You thought you were doing the right thing but you ended up making a mistake and the result is it ended up breaking the test.
4)	Developer: It seems we're arguing over nothing, because whatever exception prompted me to add this in the first place is no longer raised. I've removed it, and we can add it back if it ever becomes relevant again.
Source Code URL: https://review.opendev.org/#/c/109006/5..6/nova/tests/db/test_db_api.py@307
4.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I2755c59b4db736151000dae351fd776d3c15ca39
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: I'm really not happy with polluting the destroy + cleanup methods with arbitrary driver specific data blob like this.
The pre-existing 'destroy_disks' parameter here is involved in migration and set appropriately by the compute manager. I really think a similar approach is require here. ie any new parameter to 'cleanup' should take the form of a functional instruction of what the required behaviour of the cleanup method is.
ie IMHO this should be 'delete_instance_files=True' as a parameter, since the semantics of that nicely match the standard 'delete_instance_files' method in the virt driver API.
2)	Developer: We already had this discussion in patch set 22, the conclusion was that, even if what you're asking for were a valid approach, it would expand the scope of this patch too far beyond the bug in question.
If you really insist on pulling that discussion out of the freezer after a month and a dozen patch revisions (which by itself is another indicator that the discussion belongs in a blueprint, not bugfix review comments), here's where we left it, from my perspective.
I think that polluting signatures of methods of the parent class with implementation specific parameters (and delete_instance_files is as libvirt specific as it gets) is a recipe for the shotgun surgery anti-pattern. You don't have to go further than this very patch to observe the impact of that anti-pattern in how (at your own request in patch set 21) I had to touch all virt drivers to fix a libvirt specific problem.
Another argument I already made in patch set 22 that is worth reiterating is that the amount of driver specific information passed over RPC is likely to grow as drivers mature. And every time you need to change what you pass between two instances of the same driver, you'd have same amount of shotgun surgery all over the place, unless you encapsulate implementation specific details away from upper layers so that only the driver itself has to be changed.
Source Code URL: https://review.opendev.org/#/c/91722/34..35/nova/virt/driver.py@335
5.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I34753382677e3315ea4a71cfe9b3b82e9f9159bb
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: LGTM, although this whole VimExeption thing is very strange, and unclear on what the point is.
2)	Developer: The idea is to provide module/layer exceptions ... all things Vim related are descended from this root class... or wrapped by this root or descendant. So a higher layer can say... "if it is a VimException I can handle it by doing X."
But it is easy to slip from this pattern into these anti-patterns:
https://today.java.net/article/2006/04/04/exception-handling-antipatterns
BTW: looks like I broke some Tempest tests. Another revision shortly.
Source Code URL: https://review.opendev.org/#/c/77995/2..3/nova/virt/vmwareapi/error_util.py@46
6.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I438b31d5e66745278e3bfc17d6e0aa6f81a6616b
Code Smell Term: bad pattern
Code Smell Discussions: 
1)	Reviewer: You should move code needed for reinitialization to separate method and call it here and from __init__. Calling __init__ more than one time is error-prone.
BTW. you can fall into infinite recursion here.
2)	Reviewer: re-initializing everything is a bad pattern. See how a similar thing is done in the libvirt driver for inspiration.
3)	Developer: Done
4)	Developer: Done
Source Code URL: https://review.opendev.org/#/c/45867/10..11/nova/scheduler/vault_backends/memcache.py@56
7.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I64108338e3c958ba1276aaf113a68861cbe286f5
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: This will incur technical debt. Why not query the stevedore list of resource extensions for the names instead of duplicating this information here?
Source Code URL: https://review.opendev.org/#/c/71557/25..26/nova/tests/compute/test_resource_tracker.py@45
8.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Ia61d1380705cecbfc29d517702235582db676f53
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: I think I mentioned this in an earlier version of this patch series, but the above introduces a large surface area for error and a fair bit of technical debt. You will need to update this file every time any distribution cuts a new release :( Isn't there any way to query vSphere for these values and then cache them? Seems pretty fragile if coding for the vSphere API assumes the caller needs to constantly keep this list of strings in sync with what vSphere expects.
2)	Developer: On one level I agree with you, on another (obviously) I think it's justifiable to put this list here. For one, the list of vSphere guests is only allowed to grow by the backend API maintainers. So that means a name will never leave this list. New API versions may add to it only. So I think that mitigates the problem.
The reason I felt it important to add this list here is that it allows for eager evaluation of the parameters forcing an error sooner. If we wait for the error to occur after it reaches vSphere then we have to bubble our error up through the various network layers and make our way through the driver's various error handlers and critical context could be lost.
Error out early and a diagnosis should be easier.
The source of these image parameter strings comes from the command line and those could easily be 'fat-fingered' and entered wrong. At some point we can hopefully export these up to something that Horizon can use or port this file into oslo.vmware or another place that makes sense. The first step is solving the immediate validation problem.
Source Code URL: https://review.opendev.org/#/c/87002/2..3/nova/virt/vmwareapi/model.py@58
9.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I9244d8a47f6cc20107e2bd311dc2de5bb0a18843
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: This is going to be a PITA to keep up to date. It represents technical debt, IMO... Is there any way to query vSphere for these constants instead of introducing this dependency here?
Kind of the same for all of the constants in this file, but more important for this particular one, IMO.
Source Code URL: https://review.opendev.org/#/c/84537/1/nova/virt/vmwareapi/model.py@64

1.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~If5bcad8252ac2a634c6cbbc96e4295852ca9eae6
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: This is an anti-pattern. If context is passed, it should be the first argument. It should also not be optional, as anything creating a PciDevTracker will already have a context.
There are also several proposals to correct this already; here's my version: https://review.openstack.org/#/c/145619
2)	Developer: Thank you very much to remind me. I will fix it ASAP.
Source Code URL: https://review.opendev.org/#/c/151528/11..12/nova/pci/manager.py@46

1.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I29509e923019760d8b98ae8463c5146ae02aa4c8
Code Smell Term: code smell
Code Smell Discussions: 
1)	Reviewer: While your code is correct, the original code smells. Why creating a temporary list but don't store it? It looks like a dead simple loop, no?
for key in no_changes:
    dev_dict.pop(key, None)

[key for key in no_changes] is also strange. Why not using directly no_changes, or list(no_changes)?
Source Code URL: https://review.opendev.org/#/c/262083/43..45/nova/objects/pci_device.py@146
2.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Ib5895e8de901f1a282d0f5c0ecb811ff8b451497
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: Might not be a bug here, but tempest_test_uuids is using a mutable argument -- which generally results in surprising behavior for most Python developers. It's an anti-pattern that should be generally avoided or strongly documented when the behavior is actually desirable.
2)	Developer: Very, true. We should fix those up.
Source Code URL: https://review.opendev.org/#/c/264719/4..5/doc/ext/support_matrix.py@71
3.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Ie04d6362a4e99dcb2504698fc831a366ba746b44
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: So this is generally an anti-pattern and we should never do this.
We do a similar (even more complicated) thing with pci whitelist and it has been a massive source of sad.
I'll dub this Nikola's law: If a config option defines any kind of structure more complicated than a simple list of strings, it needs to define it's own grammar and an AST and needs to be parsed into it.
This means that if we are introducing this kind of thing in the config options - we want a set of objects to define the internal representation of the parse tree, not just the result, as that mini "language" becomes something we need to be backwards compatible with, which is impossible without a well defined structure.
2)	Reviewer: +1 to everything Nikola said above. 
You can see in [1][2] how the config option type "IPOpt" is defined. We could create a package "nova/conf/types/" where we place our Nova specific custom config option types. This has also the advantage that mistakes in the configuration get checked at service startup time, where the config options get slurped in from the "nova.conf" file, which is as early as it gets. The new option type will then host the logic from below and also raise the error you defined in another module.
References:
[1] https://github.com/openstack/oslo.config/blob/28324a7e1f272d8ec9fa491b1ccbadce29745d1b/oslo_config/cfg.py#L1195
[2] https://github.com/openstack/oslo.config/blob/28324a7e1f272d8ec9fa491b1ccbadce29745d1b/oslo_config/types.py#L551
3)	Developer: Yes it's something good to have for sure but I do not see why this should be implemented right now.
So several options are currently like that. e.g how we parse vcpu_set_pin. Except that, good point raised here.
4)	Reviewer: At some point in time we have to start. The others slipped through or it wasn't recognized as an issue back then.
5)	Developer: Yes and it's a good blueprint to purpose. That said this is just 3 integers, this does not to pretend to be a mini-language at all.
6)	Reviewer: > So several options are currently like that. e.g how we parse vcpu_set_pin. Except that, good point raised here.
All of the other ones are arguably worse since they are request_specs which are almost a public API. This is the first one that comes from a config option.
I feel that what makes this one different though, is that there is an actual structure that we build up from the config string as opposed to just simple values assigned to variables.
Markus gave some good pointers there although even with validation in a custom config option, we still won't check that there is no change in semantics.
I think it's totally fair game to ask to make this less sucky seeing that this is the very beginning of a cycle.
Source Code URL: https://review.opendev.org/#/c/292499/1..2/nova/virt/hardware.py@1264
4.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I7b7ad794b1e15dcd63344e01a520d6c595a73d70
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: IMHO, we should have a '_maybe_unmount' method int he parent class which deal with updating the mount usage cache, and calling umount in one operation.
In fact I think it be would nice to completely separate mount handling from the volume calsses.
Have a nova/virt/libvirt/mount.py file which defines a "MountManager" class. There'd a single instance of this associated with the libvirt driver, and it can be passed into the volume class constructor. This MountManager class would have mount + unmount methods, and internally maintain the cache/record of everything which is mounted.
These volume classes would simply invoke the mount/unmount methods on that class and not have to worry about anything else.
2)	Reviewer: +1
I'd personally take that as follow-on, though, unless we have somebody prepared to do the work now. I don't think this patch is adding technical debt, maybe just not reducing it as much as it might.
Source Code URL: https://review.opendev.org/#/c/290510/12..13/nova/virt/libvirt/volume/glusterfs.py@93
5.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I69522977631be2ae42ac504740c04247c75022eb
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: Thanks for looking at alternatives. I still have 2 major concerns with this approach, though.
Firstly, disk_format and container_format are actually known. The problem is that we're not propagating them from the libvirt driver. I would much prefer to fix the problem at source.
Secondly, and more seriously, this creates a unexpected and non-obvious coupling between compute/api and the libvirt driver. A future developer who fixes the problem in the libvirt driver is going to have a wtf moment when they realise that their carefully corrected data still isn't making its way to glance. Worse, they might not notice, and it's unlikely to be obvious in review either. I feel that this is more technical debt that we can't afford in this code.
2)	Developer: I'm going to need you to reproduce this bug and see the error condition for yourself before I entertain the notion of discussing this further.
While debate and discussion are almost always healthy, you have available a very small test case that would demonstrate in short order that no, the problem is not one of propagation, and that the failure occurs well before the driver is ever consulted.
You will save a tremendous amount of time if you familiarize yourself with the reported bug before commenting on the correctness of the proposed fix.
3)	Reviewer: You're absolutely right. I was thrown by the code flow here, because I didn't realise the api service creates a placeholder image first and passes it to the compute (that's pretty weird, btw; I wonder why it does that).
Anyway, in that context, this is actually an uncoupling. As you say, the driver adds these fields later, and they aren't known at this point. Omitting them here makes perfect sense.
Source Code URL: https://review.opendev.org/#/c/226069/6..7/nova/compute/api.py@2208

1.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I3155984d76df06371a6c45f633aa448168a96d64
Code Smell Term: code smell
Code Smell Discussions: 
1)	Reviewer: How is that possible if the only things that touch the state are reset_state and host_down? And host_down is in the same lock as this code in host_up.
2)	Developer: cond.wait() releases the lock while it waits and reacquires it when it finishes, which is why it's pretty much always code smell if it's not in a loop.
That said, it would be pretty hard to hit this in normal operation because it would require us to have stacked calls to host_up(). You could probably construct a way for this to occur if the libvirt connection was bouncing, but that's the purview of the driver module. The approach I've taken here is that *this* module is predictable regardless of how it is called, so we handle this.
So lets say there's a thread busy doing a mount operation which is going to take a few seconds. While this mount is ongoing, use_count is at least 1. During this time we get a call to host_down. We now have state == None, but use_count >= 1 while that mount using the old state is still ongoing. Before the mount completes, we have *2* calls to host_up. Both calls find that state == None and proceed, but they wait in the loop above for use count to reach zero. When the mount completes, the thread notifies the condition, and the 2 waiting host_up calls race to wake up. One of them wins, re-takes the condition lock, finds that state is still None, and initialises it. When it completes it releases the lock again so the other thread can also continue. This thread finds that the state has already been initialised, so does nothing.
Source Code URL: https://review.opendev.org/#/c/383859/13..14/nova/virt/libvirt/volume/mount.py@129
2.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I3b25debb0bcfd4e211734307c8d363f2b5dbc655
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: IMO, it is not a good way to create a record whose 'uuid' is null.
My idea is:
In unit tests, once create a record whose 'uuid' is not null.
Then update 'uuid' to null by 'block_device_mapping_update_or_create' method (line 3760).
2)	Developer: That sounds worse, tbh.
I've done this. It's fine.
3)	Reviewer: Agree with Takashi that adding a kwarg just for injecting a test edge case condition isn't appropriate.
When adding NULL-able fields like this, I've just manually constructed a record that looks like what the record would look like without a populated uuid field and then verified the setting of the uuid field happens properly in the _from_db_object() method of the related object.
For instance, see this test here that does this:
https://github.com/openstack/nova/blob/master/nova/tests/functional/db/test_resource_provider.py#L146-L168
4)	Reviewer: Also agree, this is an anti-pattern.
5)	Developer: As discussed on IRC, I still personally prefer this approach as it doesn't involve any code duplication. Given that it's only a few lines, though, I'll change it anyway. Also, given that it's explicitly for creating a legacy object, it's not important for future changes to be reflected in the duplicate test code.
6)	Developer: Done
Source Code URL: https://review.opendev.org/#/c/242603/25..26/nova/db/sqlalchemy/api.py@3738
3.	Code Change URL: 
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: So you're depending this having been ignored by the super() call? You popped allocation out.
Passing non-field kwargs to this init method is another odd unconventional anti-pattern introduced by this code.
Source Code URL: https://review.opendev.org/#/c/499239/4..5/nova/objects/selection.py@57
4.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I88b115ccfa00c2b4465302ad25799b37c3124c29
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Developer: I would drop this bit, it just repeats whats in the oslo def. I know other configs do this locally, but its an anti-pattern.
2)	Reviewer: +1
Source Code URL: https://review.opendev.org/#/c/408002/8..9/nova/conf/libvirt.py@363
5.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~stable/ocata~Ie3789bda6c6417249e279739b80a61c5b525421f
Code Smell Term: bad pattern
Code Smell Discussions: 
1)	Reviewer: Hmm, this should be in a finally block so we don't break the global if we fail here I think. Granted, if this test fails, cascading test fails aren't going to make this any less broken, but it's a bad pattern.
Source Code URL: https://review.opendev.org/#/c/512406/3..4/nova/tests/unit/virt/libvirt/test_driver.py@14868
6.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Id9d255f4338e4812a10b410edf91b8d9f4f5c35e
Code Smell Term: bad pattern
Code Smell Discussions: 
1)	Reviewer: I've seen this pattern in a couple of places now. I think we need to be careful mutating the context object like this with versioned objects. I don't think it's an issue here in practice, but we need to remember that the context object we pass to get_by_filters is passed by reference, and stored in the resulting objects. This means that when we mutate it on exit from the contextmanager, we're corrupting the context objects in our list.
As I say, I don't think it's an issue in practice here. I think it would only be an issue if os-migrations tried to lazy load something, which is generally undesirable anyway. However, I still think it's a bad pattern we should probably kill early.
Note that get_admin_context() avoids this problem by returning a new context, not a mutated context. I think we should kill context.target_cell() and context.set_target_cell(), and create a new get_cell_context(context, cell_mapping) which returns a new context object. A call to set_target_cell() would be replaced with:
  context = nova_context.get_cell_context(context, cell_mapping)
This would also have the benefit of not having side-effects outside the current scope, which is easier to reason about.
Use of target_cell would be replaced with the same call, except you'd store it in a new local variable rather than replacing context.
Source Code URL: https://review.opendev.org/#/c/442685/9..10/nova/compute/api.py@4036
7.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I4d70423ca978885a982c7eb5bd1efcc024d2b777
Code Smell Term: technical debt
Code Smell Discussions: 
1)	This method is only implemented by the Ironic virt driver. We should probably add a TODO in the base class method to remove it after ocata-eol. We might even be able to remove it after n-1, so after we release Pike (Nova 16.0.0) since nova only supports n-1 on computes for rolling upgrades. But removing this at a later date would allow us to clean up some technical debt in the network allocation flows where we're passing this around.
2)	Reviewer: Done
Source Code URL: https://review.opendev.org/#/c/364413/10/nova/virt/ironic/driver.py@a672
8.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Iba2110e95e80b9511698cb7df2963fd218264c8e
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: Have I mentioned that I friggin HATE the fact that the NUMA objects -- and ONLY the NUMA objects -- have their own legacy JSON serialization routines instead of using the oslo.versionedobjects serialization primitives? :( Yet another place we need to undo all this technical debt :(
2)	Developer: Heh I commented on the same thing earlier.
Source Code URL: https://review.opendev.org/#/c/282407/20..21/nova/virt/hyperv/hostops.py@178	

1.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Ice45f64546cb05db4c6f2928af0efd484f3a6aaf
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: General nit: I tend to think the plethora of internal methods in here is an anti-pattern and makes it harder to read/maintain. I know you're following a pattern, but....
It's something for which we killed the vmware driver spawn() method years ago because it was like 500 LOC full of inner methods.
2)	Reviewer: BTW, don't feel the need to change it in this change - I'm just expressing a style preference. Some others like it this way.
Source Code URL: https://review.opendev.org/#/c/564441/24..25/nova/virt/libvirt/driver.py@6258
2.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I0ae2dbf66241207a425bf7d0fc02a4d2e2dea409
Code Smell Term: anti-pattern
Code Smell Discussions: 
1)	Reviewer: This is an anti-pattern. You're basically establishing an API between L3289 and the deeeeep layers of image code way below. Why are you doing this? It makes it so much harder to debug/fix later.
2)	Developer: I followed the stack trace for booting an image to determine where to pass trusted_certs, and this was part of it. I'm not sure how else to tell image.cache() to use trusted_certs
Source Code URL: https://review.opendev.org/#/c/479949/34..35/nova/virt/libvirt/driver.py@3388
3.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~I8ec3a3a697e55941ee447d0b52d29785717e4bf0
Code Smell Term: bad pattern
Code Smell Discussions: 
1)	Reviewer: Noting here really just to raise awareness of a thing: this is just code motion here so it's not introducing a new bug. It does slightly increase the scope of the bug making it slightly more likely to race, but I doubt that's significant.
utils.temporary_mutation(context) is a bad pattern because it modifies an object which can be shared between threads of execution. For example, it's shared across all threads spawned by _do_build_and_run_instance, live migration and its monitor, and all threads spawned by sync_power_states. Probably more, this was just a cursory search for 'spawn_n'. Especially with something like lazy loading, it's really hard to guarantee that we're never going to end up here while the context object is in use elsewhere. Even if we can it's a large, ongoing, non-obvious mental effort which, if we forget it, could result in some seriously bizarre bugs. We should think about refactoring all uses of utils.temporary_mutation(context) to something which returns a copy.
2)	Developer: This is a common pattern in nova (that temporary_mutation helper has existed for a long time). We know it has implications, but I'm not sure it really matters that much for this case. Many of the spawn() things you're talking about would be stopped in their tracks once an instance is deleted anyway.
I can use an obj_alternate_context() level in here with a cloned context if people want, which will avoid mutating the one we've got here.
3)	Reviewer: Yeah, I don't think it's necessary to change here. I just think it would be good to phase it out everywhere over time, especially as the code change from context manager to copy is trivial. It's one of those things whose potential interactions are large and unpredictable: it would be simpler to reason about Nova in general if it didn't exist.
Source Code URL: https://review.opendev.org/#/c/575190/2..3/nova/objects/instance.py@1111
4.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Iedd3fea0e86648fae364f075915555dcb2c4f199
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Reviewer: This isn't the only boot from volume case, you can also boot from volume where source_type is 'image' so the conditional block above where image_is is not None or via volume snapshot which is the conditional block below where snapshot_id is not None - in both of those cases nova-compute will create a volume from either the image or volume snapshot and we won't have done image validation with the trusted_certs. Also, I think the validation would only apply to the root BDM since that's the one with the guest image in it - see BlockDeviceMappingList.root_bdm or BlockDeviceMapping.is_root.
2)	Reviewer: I've started a mailing list thread about my concerns with trusted_certs support and not supporting boot from volume:
http://lists.openstack.org/pipermail/openstack-dev/2018-April/129494.html
Over the years we've added a lot of technical debt to nova by adding new features which don't consider boot from volume (backup, rebuild, rescue, etc) and then we have to retrofit that support later which is painful, so I'd like us to at least slow down and consider this first and get broader input.
3)	Reviewer: Thanks, Matt. I'll keep an eye on the thread. For now, I'll just add checks where volume-backed instances are being created/rebuilt.
4)	Reviewer: Thanks for pointing that out. It looks like L1089 may be a better place to put this check.
5)	Reviewer: I've added the following policy rules with the latest patch set:
os_compute_api:servers:create:trusted_certs
os_compute_api:servers:rebuild:trusted_certs
We skip the policy check if no trusted_certs were provided to server create or server rebuild.
Specific policy changes:
https://review.openstack.org/#/c/486204/94..95
	Source Code URL: https://review.opendev.org/#/c/486204/92..93/nova/compute/api.py@1345
5.	Code Change URL: https://review.opendev.org/#/q/openstack/nova~master~Ibf210dd27972fed2651d6c9bd73a0bcf352c8bab
Code Smell Term: technical debt
Code Smell Discussions: 
1)	Developer: that is the crux of the problem.
Given libvirt is very limited, see the release note about the existing caveats. I'll provide separate changes for trying to workaround each caveat, but I preferred to keep that specific implementation change idealistic, in order to draw the clear line in between what is the expected behaviour, and what is just technical debt because $libvirt
Source Code URL: https://review.opendev.org/#/c/528832/4..5/nova/virt/libvirt/driver.py@4923
